/*
 * @Author: zyp yangpeng.zhang@fts.aero
 * @Date: 2024-05-27 17:48:34
 * @LastEditors: zyp yangpeng.zhang@fts.aero
 * @LastEditTime: 2024-07-05 14:24:37
 * @FilePath: \vue3-dynamic-module\src\modules\modulesManager.ts
 * @Description: 程式描述
 */
import router from '@/router';
import Layout from '@/layout/index.vue';
import configApi from '@/api/model/config';

const _window = window as any;

interface IModulesManager {
  name: string;
  description?: string;
  // ...其他属性和方法
}

const loadScript = (url:any) => {
  return new Promise((resolve:any, reject:any) => {
    const script = document.createElement('script')
    // 加载成功
    script.onload = () => {
      resolve({
        url,
        success: true
      })
    }
    // 加载失败
    script.onerror = (error) => {
      resolve({
        url,
        success: false,
        error
      })
    }

    script.src = url

    const head = document.head || document.getElementsByTagName('head')[0]
    ;(document.body || head).appendChild(script);
  })
}

// 动态加载CSS文件的函数
export const loadCSS = (href: string) => {
  const cssLink = document.createElement("link");
  cssLink.rel = "stylesheet";
  cssLink.type = "text/css";
  cssLink.href = href;
  document.head.appendChild(cssLink);
}

//动态加载外部js
//@param RESOURCE_LIST 外部地址集合["address"]
export function loadVoLteResourceList (RESOURCE_LIST:any, success?:any) {
  return Promise.all(RESOURCE_LIST.map((url:string) => loadScript(url)));
}

// 获取模块名
const getModuleName = (inputString: string): string => {
  const regex = /\/([^/]+)\.umd\.js$/;
  const match = inputString.match(regex);
  if (match) {
    return match[1];
  } else {
    return '';
  }
}

// 模块管理类
class ModulesManager<T extends IModulesManager> {
  private modules: { [key: string]: T };
  protected app: any;

  constructor(app: any) {
    this.modules = {};
    this.app = app;
  }

  // 获取所有模块
  public async importModules(): Promise<any> {
    return new Promise(async (resolve, reject) => {
      const _windowJsList: string[] = [];
      const _windowModules: any[] = [];
      // const response = await configApi.getConfig();
      const response = (window as any).config;
      console.log('服务器返回值', response);
      for (const key in response) {
        if (Object.prototype.hasOwnProperty.call(response, key)) {
          const element = response[key];
          if (Number(element.loaded) === 1) {
            _windowJsList.push(`./Modules/${key}/${key}.umd.js`);
            // _windowJsList.push(`${import.meta.env.VITE_STATIC}/${key}/${key}.umd.js?t=${+new Date()}`);
            _windowModules.push({
              name: key,
              element,
            })
          }
        }
      }
      loadVoLteResourceList(_windowJsList).then(() => {
        _windowModules.map(item => {
          if(_window[item.name]){
            const config = Object.assign({}, item.element, _window[item.name].config);
            this.app?.use(_window[item.name], {
              router,
              Layout: Layout,
            });
            this.addProject(item.name, config);
            loadCSS(`./Modules/${item.name}/style.css`);
            // loadCSS(`${import.meta.env.VITE_STATIC}/${item.name}/style.css?t=${+new Date()}`);
            const tree = this.app.config.globalProperties[`${item.name}RouterTree`];
            import.meta.env.MODE === `development` && tree.children.forEach((element: any) => {
              console.log(element);
              element.component = defineAsyncComponent(() =>
                import(/*@vite-ignore*/ element.compurl)
              );
            });
            router.addRoute(tree)
            console.log(`%c[${item.name}]Successfully loaded`, 'color: #67C23A; font-size: 16px;');
          }else{
            console.log(`%c[${item.name}]Loading failed`, 'color: #F56C6C; font-size: 16px;');
          }
        })
      }).catch((error) => {
        reject(error);
      }).finally(() => {
        resolve(true);
      });
    });
  }

  // 添加项目
  public addProject(name: string, value: T): void {
    this.modules[name] = value;
  }

  // 删除项目
  public removeProject(projectName: string): void {
    delete this.modules[projectName];
  }

  // 获取所有项目
  public getProjects(): { [key: string]: T } {
    return this.modules;
  }

  getListByType(type: string): T[] {
    const result = [];
    for (const key in this.modules) {
      if (Object.prototype.hasOwnProperty.call(this.modules, key)) {
        const element:any = this.modules[key];
        if(element.type === type){
          result.push(element);
        }
      }
    }
    return result;
  }

  getListByPosition(position: string): T[] {
    const result = [];
    for (const key in this.modules) {
      if (Object.prototype.hasOwnProperty.call(this.modules, key)) {
        const element:any = this.modules[key];
        if(element.position === position){
          result.push(element);
        }
      }
    }
    return result;
  }
}

export default ModulesManager;
